﻿using DataWorks_Tools.BasicMethods;
using DataWorks_Tools.MappModals;
using System.Reflection;
using System.Text;

namespace DataWorks_Tools.MileageCalDetails

{
    public static class MileageCalculation
    {
        /// <summary>
        /// 获取某个路径下所有的csv文件并按名称排序
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static FileInfo[] GetCSVFiles(this string filePath)
        {
            DirectoryInfo root = new DirectoryInfo(filePath);
            if (!root.Exists)
            {
                root.Create();
            }
            var files = root.GetFiles("*.csv").OrderBy(a => a.Name).ToArray();
            if (files != null)
            {
                return files;
            }
            else
            {
                return new FileInfo[0];
            }

        }
        /// <summary>
        /// 输入两个字符串List，输出这2个字符串中相同的元素组成的新Array
        /// </summary>
        /// <param name="list1"></param>
        /// <param name="list2"></param>
        /// <returns></returns>
        static string[] FindCommonElements(List<string> list1, List<string> list2)
        {
            List<string> commonElements = list1.Intersect(list2).OrderBy(x => x).ToList();
            return commonElements.ToArray();
        }

        /// <summary>
        /// 从用户输入的起始日期和结束日期来筛选出需要处理的日期文件夹路径数组（包含路径）,用户输入不能跳年
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        public static string[] GetDirectoryArrayfromDate(MileageCalculationModel row)
        {
            if (row.startdate != null && row.enddate != null)
            {
                //获得结束日期与起始日期之间的天数
                int span = DateTimeMethods.YXHDateDiff(row.startdate, row.enddate);
                if (row.originaldatapath != null)
                {
                    //创建一个usernames，把客户输入的2个日期之间的日期文件夹名称存入此List中
                    List<string> usernames = new List<string>();
                    //先获取客户输入的起始日期
                    DateTime date = DateTime.ParseExact(row.startdate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                    //获得起始日期的几月及几日形式
                    string startdatename = date.ToString("MM_dd");
                    //先放入客户输入的起始日期名称
                    usernames.Add(startdatename);
                    for (int i = 0; i < span; i++)
                    {
                        var newdate = date.AddDays(i + 1);
                        usernames.Add(newdate.ToString("MM_dd"));
                    }
                    //获取路径下的所有文件夹的路径
                    var directories = Directory.GetDirectories(row.originaldatapath);
                    //创建一个originalnames，把路径下的所有日期文件夹名称存入此List中
                    List<string> originalnames = new List<string>();
                    foreach (string subDir in directories)
                    {
                        string folderName = new DirectoryInfo(subDir).Name;
                        originalnames.Add(folderName);
                    }
                    //查看起始日期文件夹名称在List里的index序号
                    var resultnames = FindCommonElements(originalnames, usernames);
                    var result = resultnames.Select(a => Path.Combine(row.originaldatapath, a)).ToArray();
                    return result;
                }
                else
                {
                    return new string[0];
                }
            }
            else
            {
                return new string[0];
            }
        }

        /// <summary>
        /// 读取某个csv文件中的指定名称列数据并保存为List<double>返回
        /// </summary>
        /// <param name="filefullpath"></param>
        /// <param name="monitortimes"></param>
        /// <returns></returns>
        public static async Task<List<double>> CSVFileSelectChantitleAsync(this string filefullpath, string channame)
        {
            List<double> results = new List<double>();
            if (!filefullpath.YXHCheckFileIsUsed())
            {
                if (!filefullpath.YXHFileIsZero())
                {
                    await Task.Run(() =>
                    {
                        Encoding encoding = Encoding.Default;
                        using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs, encoding);
                        string? strLine = "";
                        //记录每行记录中的各字段内容
                        string[]? aryLine = null;
                        string[]? tableHead = null;
                        //int columnCount = 0;
                        //标示是否是读取的第一行
                        bool IsFirst = true;
                        int spdidx = -1;
                        while ((strLine = sr.ReadLine()) != null)
                        {
                            if (IsFirst == true)
                            {
                                //改为小写，去掉下划线，空格和N
                                tableHead = strLine.ReName().Split(',');
                                spdidx = tableHead.ToList().IndexOf(channame.ReName());
                                IsFirst = false;
                                if (spdidx == -1)
                                {
                                    results.Add(-1.0);
                                    break;
                                }
                            }

                            else
                            {
                                aryLine = strLine.Split(',');
                                //判断是否需要读取数据，因为有降低采样数
                                if (spdidx > -1 && spdidx < tableHead?.Length)
                                {
                                    var success = double.TryParse(aryLine[spdidx], out double number);
                                    if ((!double.IsNaN(number)))
                                    {
                                        results.Add(number);
                                    }
                                    else
                                    {
                                        results.Add(-1.0);
                                    }
                                }

                            }
                        }
                        sr.Close();
                        sr.Dispose();
                        fs.Close();
                        fs.Dispose();
                    });
                }

            }

            return results;
        }
        /// <summary>
        /// 读取某个csv文件中的指定列号数据并保存为List<double>返回
        /// </summary>
        /// <param name="filefullpath"></param>
        /// <param name="idx"></param>
        /// <returns></returns>
        public static async Task<List<double>> CSVFileSelectChanidxAsync(this string filefullpath, int idx)
        {
            List<double> results = new List<double>();
            if (!filefullpath.YXHCheckFileIsUsed())
            {
                if (!filefullpath.YXHFileIsZero())
                {
                    await Task.Run(() =>
                    {
                        Encoding encoding = Encoding.Default;
                        using FileStream fs = new FileStream(filefullpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
                        StreamReader sr = new StreamReader(fs, encoding);
                        string? strLine = "";
                        //记录每行记录中的各字段内容
                        string[]? aryLine = null;
                        string[]? tableHead = null;
                        //int columnCount = 0;
                        //标示是否是读取的第一行
                        bool IsFirst = true;
                        while ((strLine = sr.ReadLine()) != null)
                        {
                            if (IsFirst == true)
                            {
                                //改为小写，去掉下划线，空格和N
                                tableHead = strLine.ReName().Split(',');
                                IsFirst = false;
                            }
                            else
                            {
                                aryLine = strLine.Split(',');
                                var success = double.TryParse(aryLine[idx], out double number);
                                if ((!double.IsNaN(number)))
                                {
                                    results.Add(number);
                                }
                                else
                                {
                                    results.Add(-1.0);
                                }
                            }
                        }
                        sr.Close();
                        sr.Dispose();
                        fs.Close();
                        fs.Dispose();
                    });
                }

            }

            return results;
        }


        /// <summary>
        /// 此方法读取所有第一个csv和最后一个csv文件的ODO然后计算里程  返回-1说明没有一个csv的odo是可以用的，返回-2说明csv文件数量为0
        /// </summary>
        /// <param name="path"></param>
        /// <param name="monitortimes"></param>
        /// <param name="lasttime"></param>
        /// <returns></returns>
        public static async Task<double> GetTotalMileagesfromODO(this string path, string odo)
        {
            var filelist = path.GetCSVFiles();
            if (filelist.Length > 0)
            {
                double firstodo = 1, lastodo = 0;
                //先从前面取csv
                for (int i = 0; i < filelist.Length; i++)
                {
                    var firstfile = filelist[i];
                    //获得csv的odo数据集
                    var firstlist = await firstfile.FullName.CSVFileSelectChantitleAsync(odo);
                    if (firstlist.Count > 0)
                    {
                        if (firstlist.First() > 0)
                        {
                            firstodo = firstlist.First();
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                //再从后面取csv
                for (int i = filelist.Length - 1; i > 0; i--)
                {
                    var lastfile = filelist[i];
                    //获得csv的odo数据集
                    var lastlist = await lastfile.FullName.CSVFileSelectChantitleAsync(odo);
                    if (lastlist.Count > 0)
                    {
                        if (lastlist.First() > 0)
                        {
                            lastodo = lastlist.First();
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                double total = lastodo - firstodo;
                if (total >= 0)
                {
                    return Math.Round(total, 2);
                }
                else
                {
                    return -1;
                }
            }
            else
            {
                return -2;
            }
        }

        /// <summary>
        /// 此方法读取所有第一个csv和最后一个csv文件的ODO然后计算里程  返回-1说明没有一个csv的odo是可以用的，返回-2说明csv文件数量为0
        /// </summary>
        /// <param name="path"></param>
        /// <param name="monitortimes"></param>
        /// <param name="lasttime"></param>
        /// <returns></returns>
        public static async Task<double> GetTotalMileagesfromODO(this FileInfo[] files, string odo)
        {
            if (files.Length > 0)
            {
                double firstodo = 1, lastodo = 0;
                //先从前面取csv
                for (int i = 0; i < files.Length; i++)
                {
                    var firstfile = files[i];
                    //获得csv的odo数据集
                    var firstlist = await firstfile.FullName.CSVFileSelectChantitleAsync(odo);
                    if (firstlist.Count > 0)
                    {
                        if (firstlist.First() > 0)
                        {
                            firstodo = firstlist.First();
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                //再从后面取csv
                for (int i = files.Length - 1; i > 0; i--)
                {
                    var lastfile = files[i];
                    //获得csv的odo数据集
                    var lastlist = await lastfile.FullName.CSVFileSelectChantitleAsync(odo);
                    if (lastlist.Count > 0)
                    {
                        if (lastlist.First() > 0)
                        {
                            lastodo = lastlist.First();
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                double total = lastodo - firstodo;
                if (total >= 0)
                {
                    return Math.Round(total, 2);
                }
                else
                {
                    return -1;
                }
            }
            else
            {
                return -2;
            }
        }

        /// <summary>
        /// 只返回单个里程，不返回累积里程
        /// </summary>
        /// <param name="speed"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public static async Task<List<double>> ReturnSingleDistance(List<double> speed, List<double> time)
        {
            List<double> Distance = new List<double>
            {
                0
            };
            double singledistance;
            await Task.Run(() => {

                for (int i = 0; i < speed.Count - 1; i++)
                {
                    singledistance = (speed[i] + speed[i + 1]) * (time[i + 1] - time[i]) / 2 / 3.6;
                    Distance.Add(singledistance);
                }

            });
            return Distance;
        }


    }
}
